/*************************************************************
   Copyright(C) 2017 by WuIslet
   All rights reserved.
   
   FindInPrefab.cs
   UnityFramework
   
   Created by WuIslet on 2018-02-01.
   
*************************************************************/
#define USE_EDITOR_UI_CONTROLDATA
#if !USE_ILRUNTIME

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using DG.Tweening;
//using Framework.EffectSystem;
//using Example;
using TMPro;
using UnityEditor;
using UnityEditor.Animations;
using UnityEngine;
using UnityEngine.UI;
//using X2Engine;
using Path = System.IO.Path;
using Vector3 = UnityEngine.Vector3;

public partial class FindInPrefab
{
    static readonly int ShaderProperty_MainTex = Shader.PropertyToID("_MainTex");
    private const System.Reflection.BindingFlags BIND_TYPE =
        System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public |
        System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Static;

    // 3. 后续处理 AfterDealClass
    private enum AfterDeal
    {
        // 通用方法
        打印详细,
        打印树结构,
        参数查找替换,
        调用指定函数,
        比较尺寸,
        修改tag,
        删除节点,
        查找Prefab里的资源依赖,
        含有Component,
        增删Component,

        //UI规范化。包含以下功能：
        //  基础格式检查，
        //  Transform清除小数点，
        //  RayCast删除，
        //  Navigation关闭，
        //  z值设置为0，
        //  空的CanvasRender，
        //  空的DOTweenAnimation，
        //  删除非法空字符：\x0d
        //  检查资源的路径是不是来自非法路径:FORBID_UI_PATH
        //  LazyEffectPlayer路径修复
        //  TODO 替换miss/none资源为白底
        //  TODO 替换图集
        UI规范化,

        // 特殊Component对应方法
        文字射线,
        默认字体,
        检查TMP的边距,
        检查UI材质,
        查找未使用图集的Image,
        //分析prefab成分

        //UISceneTool方法
        调用UISceneTool方法,

        //X2
        //blur修复,
        //文字控件解析,
        //文字控件查找,
        根据tag把文字引用中的程序修改文字剔除,
        动画表情散图查找替换,

        //xglm
        检查UIAni2动画格式,
        检查按钮Highlight命名,
        uiani2后处理,

        //lp
        检查SingleFrameAni序列帧命名规范,

        //非gameobject方法
        检查controller下的动画是否有legacy,
        检查controller下的状态机是否为空motion,
        一键替换LanguageID,
    }
    private static AfterDeal mAfterDeal;
    private static Dictionary<AfterDeal, Phase<FindResult, string>> AfterDealClass;

    private static void ResetAfterDeal()
    {
        AfterDealClass = new Dictionary<AfterDeal, Phase<FindResult, string>>
        {
            // 通用方法
            {AfterDeal.打印详细, new AfterDealPrintDetail() },
            {AfterDeal.打印树结构, new AfterDealPrintTree() },
            {AfterDeal.参数查找替换, new AfterDealPrintParam() },
            {AfterDeal.调用指定函数, new AfterDealCallFunction() },
            {AfterDeal.比较尺寸, new AfterDealCheckSize() },
            {AfterDeal.修改tag, new AfterDealChangeTag() },
            {AfterDeal.删除节点, new AfterDealDeleteGameobject() },
            {AfterDeal.查找Prefab里的资源依赖, new AfterDealGetDependencies() },
            {AfterDeal.含有Component, new AfterDealHasComponent() },
            {AfterDeal.增删Component, new AfterDealComponentTool() },

            {AfterDeal.UI规范化, new AfterDealFormatPrefab() },

            // 特殊Component对应方法
            {AfterDeal.文字射线, new AfterDealTextRaycast() },
            {AfterDeal.默认字体, new AfterDealDefaultFont() },
            {AfterDeal.检查TMP的边距, new AfterDealTMPMargins() },
            {AfterDeal.检查UI材质, new AfterDealNoneImage() },
            {AfterDeal.查找未使用图集的Image, new AfterDealUnTGAImage() },
            //{AfterDeal.分析prefab成分, new AfterDealAnalyzePrefab() },
            
            //UISceneTool方法
        
            //X2
            //{AfterDeal.blur修复, new AfterDealBlurPrefab() },
            //{AfterDeal.文字控件解析, new AfterDealX2UIWindowAsset() },
            //{AfterDeal.文字控件查找, new AfterFindX2UIWindowAsset() },
            {AfterDeal.根据tag把文字引用中的程序修改文字剔除, new AfterFindX2UIControlDataTagAsset() },
            {AfterDeal.动画表情散图查找替换, new AfterDealX2ExpressionReplaceSprite() },
            
            //xglm
            {AfterDeal.检查按钮Highlight命名, new AfterDealCheckButtonHighlightedName() },

            //lp
            {AfterDeal.检查SingleFrameAni序列帧命名规范, new AfterDealCheckSingleFrameAniSpriteName() },

            {AfterDeal.检查controller下的动画是否有legacy, new AfterDealControllerLegacy() },
            {AfterDeal.检查controller下的状态机是否为空motion, new AfterDealControllerEmptyState() },
            {AfterDeal.一键替换LanguageID, new AfterDealReplaceLanguageID() },
        };
    }

    #region class 打印详细
    class AfterDealPrintDetail : Phase<FindResult, string>
    {
        override public string FuncReturn(FindResult input)
        {
            var str = "";
            if (input != null)
            {
                str = input.path;
                if (!string.IsNullOrEmpty(input.extra))
                {
                    str += " <extra: " + input.extra + ">";
                }

                if (input.extraObjs != null && input.extraObjs.Count > 0)
                {
                    str += " <extra Objs: ";
                    for (int i = 0; i < input.extraObjs.Count; ++i)
                    {
                        str += input.extraObjs[i] == null ? "null" : (input.extraObjs[i]) + ", ";
                    }
                    str += ">";
                }
            }
            return str;
        }
    }
    #endregion class 打印详细

    #region class 打印树结构
    class AfterDealPrintTree : Phase<FindResult, string>
    {
        override public string FuncReturn(FindResult input)
        {
            var str = "";
            if (input != null)
            {
                var result = BFSPrefab(input, null);
                for (int i = 0, len = result.Count; i < len; ++i)
                {
                    var findResult = result[i];
                    str += findResult.path;
                    str += "\r\n";
                }
            }
            return str;
        }

        override public string CheckNeed(bool isSave, SearchRange sr, bool isDS, HitRule hr, AfterDeal ad)
        {
            if (isSave)
            {
                return "不需要需要启用保存prefab功能";
            }

            if (isDS)
            {
                return "不可以启用深度搜索";
            }

            return "";
        }
    }
    #endregion class 打印树结构

    #region class 参数查找替换
    class AfterDealPrintParam : Phase<FindResult, string>
    {
        private enum ArgType
        {
            整数,
            布尔值,
            字符串,
            Sprite图片,
            位运算,
        }

        private string component;
        private string propertyName;
        private bool isEqual;
        private bool isReplace;
        private ArgType argType;
        private int intValue;
        private int intNewValue;
        private bool boolValue;
        private bool boolNewValue;
        private string strValue;
        private string strNewValue;
        private Sprite sprValue;
        private Sprite sprNewValue;
        private int bitValue;
        private int bitNewValue;
        private List<string> propertyNameList = new List<string>();
        override public string FuncReturn(FindResult input)
        {
            var str = "";
            object com = null;
            if (component == "GameObject")
            {
                com = input.go;
            }
            else
            {
                com = input.go.GetComponent(component);
            }
            if (com != null)
            {
                var value = ReflectionHelper.GetValue(com, propertyName);
                if (value != null)
                {
                    if (isEqual)
                    {
                        if (argType == ArgType.整数)
                        {
                            if ((int)value == intValue)
                            {
                                if (isReplace)
                                {
                                    ReflectionHelper.SetValue(com, propertyName, intNewValue);
                                }
                                str = input.path;
                            }
                        }
                        else if (argType == ArgType.布尔值)
                        {
                            if ((bool)value == boolValue)
                            {
                                if (isReplace)
                                {
                                    ReflectionHelper.SetValue(com, propertyName, boolNewValue);
                                }
                                str = input.path;
                            }
                        }
                        else if (argType == ArgType.字符串)
                        {
                            if ((string)value == strValue)
                            {
                                if (isReplace)
                                {
                                    ReflectionHelper.SetValue(com, propertyName, strNewValue);
                                }
                                str = input.path;
                            }
                        }
                        else if (argType == ArgType.Sprite图片)
                        {
                            if ((value as Sprite) == sprValue)
                            {
                                if (isReplace)
                                {
                                    ReflectionHelper.SetValue(com, propertyName, sprNewValue);
                                }
                                str = input.path;
                            }
                        }
                        if (argType == ArgType.位运算)
                        {
                            if ((((int)value) & bitValue) > 0)
                            {
                                if (isReplace)
                                {
                                    var newValue = (int)value | bitNewValue;
                                    ReflectionHelper.SetValue(com, propertyName, newValue);
                                }
                                str = input.path;
                            }
                        }
                    }
                    else
                    {
                        str = input.path + " : " + value;
                        var tryList = value as System.Collections.ICollection;
                        if (tryList != null)
                        {
                            str += " Len: " + tryList.Count;
                            if (tryList.Count > 0)
                            {
                                str += "[";
                            }
                            foreach (var listItem in tryList)
                            {
                                str += (listItem + ", ");
                            }
                            str += "]";
                        }
                    }
                }
                else
                {
                    str = input.path + " is null";
                    //报错处理
                }
            }
            else
            {
                //报错处理
            }
            return str;
        }

        override public void OnDraw()
        {
            EditorGUILayout.BeginHorizontal();
            component = EditorGUILayout.TextField("    控件名：", component);
            //if (GUILayout.Button("检查参数", GUILayout.MaxWidth(100)))
            //{
            //    propertyNameList.Clear();
            //    if (!string.IsNullOrEmpty(component))
            //    {
            //        var comType = Type.GetType(component);
            //        if (comType != null)
            //        {
            //            var properties = comType.GetProperties(BIND_TYPE);
            //            foreach (var pro in properties)
            //            {
            //                var name = pro.Name;
            //                if (!propertyNameList.Contains(name))
            //                {
            //                    propertyNameList.Add(name);
            //                }
            //            }

            //            var fields = comType.GetFields(BIND_TYPE);
            //            foreach (var field in fields)
            //            {
            //                var name = field.Name;
            //                if (!propertyNameList.Contains(name))
            //                {
            //                    propertyNameList.Add(name);
            //                }
            //            }
            //        }
            //    }
            //}
            EditorGUILayout.EndHorizontal();

            propertyName = EditorGUILayout.TextField("    参数名：", propertyName);
            if (propertyNameList != null && propertyNameList.Count > 0)
            {
                EditorGUILayout.BeginHorizontal();
                foreach (var key in propertyNameList)
                {
                    if (GUILayout.Button(key, GUILayout.MaxWidth(100)))
                    {
                        propertyName = key;
                    }
                }
                EditorGUILayout.EndHorizontal();
            }

            isEqual = GUILayout.Toggle(isEqual, "是否等于一个值？");
            if (isEqual)
            {
                argType = (ArgType)EditorGUILayout.EnumPopup("参数类型：", argType, GUILayout.MinWidth(100));
                switch (argType)
                {
                    case ArgType.整数:
                        intValue = EditorGUILayout.IntField(intValue);
                        break;
                    case ArgType.布尔值:
                        boolValue = EditorGUILayout.Toggle(boolValue);
                        break;
                    case ArgType.字符串:
                        strValue = EditorGUILayout.TextField(strValue);
                        break;
                    case ArgType.Sprite图片:
                        sprValue = EditorGUILayout.ObjectField(sprValue, typeof(Sprite), true) as Sprite;
                        break;
                    case ArgType.位运算:
                        bitValue = EditorGUILayout.IntField(bitValue);
                        break;
                }

                isReplace = GUILayout.Toggle(isReplace, "是否替换？");
                if (isReplace)
                {
                    switch (argType)
                    {
                        case ArgType.整数:
                            intNewValue = EditorGUILayout.IntField(intNewValue);
                            break;
                        case ArgType.布尔值:
                            boolNewValue = EditorGUILayout.Toggle(boolNewValue);
                            break;
                        case ArgType.字符串:
                            strNewValue = EditorGUILayout.TextField(strNewValue);
                            break;
                        case ArgType.Sprite图片:
                            sprNewValue = EditorGUILayout.ObjectField(sprNewValue, typeof(Sprite), true) as Sprite;
                            break;
                        case ArgType.位运算:
                            bitNewValue = EditorGUILayout.IntField(bitNewValue);
                            break;
                    }
                }
            }
            else
            {
                isReplace = false;
            }
        }

        override public string CheckNeed(bool isSave, SearchRange sr, bool isDS, HitRule hr, AfterDeal ad)
        {
            if (isSave && !isReplace)
            {
                return "不需要启用保存prefab功能";
            }
            if (!isSave && isReplace)
            {
                return "需要启用保存prefab功能";
            }

            return "";
        }
    }
    #endregion class 参数查找替换

    #region class 调用指定函数
    class AfterDealCallFunction : Phase<FindResult, string>
    {
        private string component;
        private string functionName;
        private List<string> functionNameList = new List<string>() { "SetNativeSize", "DoDuplicate" };
        override public string FuncReturn(FindResult input)
        {
            var str = "";
            var com = input.go.GetComponent(component);
            if (com != null)
            {
                ReflectionHelper.InvokMethod(com, functionName);
            }
            else
            {
                //报错处理
            }
            return str;
        }

        override public void OnDraw()
        {
            EditorGUILayout.BeginHorizontal();
            component = EditorGUILayout.TextField("    控件名：", component);
            EditorGUILayout.EndHorizontal();

            functionName = EditorGUILayout.TextField("    函数名：", functionName);
            if (functionNameList != null && functionNameList.Count > 0)
            {
                EditorGUILayout.BeginHorizontal();
                foreach (var key in functionNameList)
                {
                    if (GUILayout.Button(key, GUILayout.MaxWidth(100)))
                    {
                        functionName = key;
                    }
                }
                EditorGUILayout.EndHorizontal();
            }
        }

        override public string CheckNeed(bool isSave, SearchRange sr, bool isDS, HitRule hr, AfterDeal ad)
        {
            if (!isSave)
            {
                return "需要启用保存prefab功能";
            }

            return "";
        }
    }
    #endregion class 调用指定函数

    #region class 比较尺寸
    class AfterDealCheckSize : Phase<FindResult, string>
    {
        enum CompareType
        {
            尺寸,
            缩放,
        }

        enum CompareWay
        {
            大于,
            等于,
            小于,
        }

        enum CalculateWay
        {
            或,
            且,
            加,
            乘,
        }
        private CompareType mCompareType;
        private CompareWay mCompareWay;
        private CalculateWay mCalculateWay;
        private Vector2 mMinSize;
        override public string FuncReturn(FindResult input)
        {
            var str = "";
            var rect = input.go.transform as RectTransform;
            if (rect != null)
            {
                var result = true;
                switch (mCalculateWay)
                {
                    case CalculateWay.加:
                        if (mCompareType == CompareType.尺寸)
                        {
                            result = Compare(rect.rect.width + rect.rect.height, mMinSize.x + mMinSize.y);
                        }
                        else if (mCompareType == CompareType.缩放)
                        {
                            result = Compare(rect.localScale.x + rect.localScale.y, mMinSize.x + mMinSize.y);
                        }
                        break;
                    case CalculateWay.乘:
                        if (mCompareType == CompareType.尺寸)
                        {
                            result = Compare(rect.rect.width * rect.rect.height, mMinSize.x * mMinSize.y);
                        }
                        else if (mCompareType == CompareType.缩放)
                        {
                            result = Compare(rect.localScale.x * rect.localScale.y, mMinSize.x * mMinSize.y);
                        }
                        break;
                    case CalculateWay.且:
                        if (mCompareType == CompareType.尺寸)
                        {
                            result = Compare(rect.rect.width, mMinSize.x) && Compare(rect.rect.height, mMinSize.y);
                        }
                        else if (mCompareType == CompareType.缩放)
                        {
                            result = Compare(rect.localScale.x, mMinSize.x) && Compare(rect.localScale.y, mMinSize.y);
                        }
                        break;
                    case CalculateWay.或:
                        if (mCompareType == CompareType.尺寸)
                        {
                            result = Compare(rect.rect.width, mMinSize.x) || Compare(rect.rect.height, mMinSize.y);
                        }
                        else if (mCompareType == CompareType.缩放)
                        {
                            result = Compare(rect.localScale.x, mMinSize.x) || Compare(rect.localScale.y, mMinSize.y);
                        }
                        break;
                }

                if (result)
                {
                    str = string.Format("{0} size:({1}, {2}) scale:({3}, {4})", input.path, rect.rect.width, rect.rect.height, rect.localScale.x, rect.localScale.y);
                }
            }
            return str;
        }

        private bool Compare(float x1, float x2)
        {
            switch (mCompareWay)
            {
                case CompareWay.大于:
                    return x1 > x2;
                case CompareWay.等于:
                    return Mathf.Abs(x1 - x2) < float.Epsilon;
                case CompareWay.小于:
                    return x1 < x2;
            }

            return false;
        }

        override public void OnDraw()
        {
            EditorGUILayout.BeginVertical("Box");
            EditorGUILayout.BeginHorizontal();
            mCompareType = (CompareType)EditorGUILayout.EnumPopup("比较对象：", mCompareType, GUILayout.MinWidth(100));
            mCompareWay = (CompareWay)EditorGUILayout.EnumPopup("比较方法：", mCompareWay, GUILayout.MinWidth(100));
            mCalculateWay = (CalculateWay)EditorGUILayout.EnumPopup("计算方法：", mCalculateWay, GUILayout.MinWidth(100));
            EditorGUILayout.EndHorizontal();
            mMinSize = EditorGUILayout.Vector2Field("比较尺寸", mMinSize);
            EditorGUILayout.EndVertical();
        }

        override public string CheckNeed(bool isSave, SearchRange sr, bool isDS, HitRule hr, AfterDeal ad)
        {
            if (!isDS)
            {
                return "需要启用深度查找功能";
            }
            if (hr == HitRule.None)
            {
                return "需要启用命中判断";
            }
            return "";
        }
    }
    #endregion class 比较尺寸

    #region class 修改tag
    class AfterDealChangeTag : Phase<FindResult, string>
    {
        private string[] example = new[] { "Untagged", "EditorOnly", "UI_ControlData" };
        private string newTag = "";
        override public string FuncReturn(FindResult input)
        {
            var str = "";
            input.go.tag = newTag;
            str += input.path;
            return str;
        }

        override public void OnDraw()
        {
            newTag = EditorGUILayout.TextField("    新的tag：", newTag);
            EditorGUILayout.BeginHorizontal();
            foreach (var key in example)
            {
                if (GUILayout.Button(key, GUILayout.MaxWidth(100)))
                {
                    newTag = key;
                }
            }
            EditorGUILayout.EndHorizontal();
        }

        override public string CheckNeed(bool isSave, SearchRange sr, bool isDS, HitRule hr, AfterDeal ad)
        {
            if (!isSave)
            {
                return "需要启用保存prefab功能";
            }
            return "";
        }
    }
    #endregion class 修改tag

    #region class 删除节点
    class AfterDealDeleteGameobject : Phase<FindResult, string>
    {
        override public string FuncReturn(FindResult input)
        {
            var str = "";
            str = input.path;
            if (input.isGameObject())
            {
                GameObject.DestroyImmediate(input.go, true);
            }
            else
            {
                var path = Path.Combine(Application.dataPath, "..", AssetDatabase.GetAssetPath(input.rawObj));
                File.Delete(path);
                input.rawObj = null;
                input.go = null;
                str = path;
            }
            return str;
        }

        override public void OnDraw()
        {
            EditorGUILayout.HelpBox("删除节点操作不可逆，请谨慎使用", MessageType.Warning);
        }

        override public string CheckNeed(bool isSave, SearchRange sr, bool isDS, HitRule hr, AfterDeal ad)
        {
            if (!isSave)
            {
                return "需要启用保存prefab功能";
            }
            if (hr == HitRule.None)
            {
                return "需要启用命中判断";
            }
            return "";
        }
    }
    #endregion class 删除节点

    #region class 查找Prefab里的资源依赖
    class AfterDealGetDependencies : Phase<FindResult, string>
    {
        private string extString = ".tga|.png|.jpg";
        override public string FuncReturn(FindResult input)
        {
            var str = "";
            var list = extString.Split('|');
            var path = AssetDatabase.GetAssetPath(input.rawObj);
            foreach (var resourcesName in AssetDatabase.GetDependencies(path))
            {
                for (int i = 0; i < list.Length; i++)
                {
                    var ext = list[i];
                    if (resourcesName.EndsWith(ext))
                    {
                        str += resourcesName;
                        str += "\r\n";
                        break;
                    }
                }
            }
            return str;
        }

        override public void OnDraw()
        {
            extString = EditorGUILayout.TextField(extString);
        }

        override public string CheckNeed(bool isSave, SearchRange sr, bool isDS, HitRule hr, AfterDeal ad)
        {
            if (isDS)
            {
                return "查找Prefab里的资源依赖暂时不支持深度查找";
            }
            return "";
        }
    }
    #endregion class 查找Prefab里的资源依赖

    #region class 含有Component
    class AfterDealHasComponent : Phase<FindResult, string>
    {
        private bool findWithString = true;
        private bool reverse = false;
        private string[] example = new[] { "Graphic", "Selectable", "Text", "TextMeshProUGUI", "Animator", "Button" };
        private string component;
        private MonoScript scriptObj;
        override public string FuncReturn(FindResult input)
        {
            var str = "";

            if (findWithString)
            {
                if (string.IsNullOrEmpty(component))
                {
                    str += input.path + "\r\n";
                }
                else
                {
                    if (reverse)
                    {
                        if (input.go.GetComponent(component) == null)
                            str += input.path + "\r\n";
                    }
                    else
                    {
                        if (input.go.GetComponent(component) != null)
                            str += input.path + "\r\n";
                    }
                }
            }
            else
            {
                if (scriptObj == null)
                {
                    str += input.path + "\r\n";
                }
                else
                {
                    if (reverse)
                    {
                        if (input.go.GetComponent(scriptObj.GetClass()) == null)
                            str += input.path + "\r\n";
                    }
                    else
                    {
                        if (input.go.GetComponent(scriptObj.GetClass()) != null)
                            str += input.path + "\r\n";
                    }
                }
            }

            return str;
        }

        override public void OnDraw()
        {
            reverse = GUILayout.Toggle(reverse, "查找缺少该控件的？");
            findWithString = GUILayout.Toggle(findWithString, "使用名字查找？");
            if (findWithString)
            {
                component = EditorGUILayout.TextField("    控件名：", component);
                EditorGUILayout.BeginHorizontal();
                foreach (var key in example)
                {
                    if (GUILayout.Button(key, GUILayout.MaxWidth(100)))
                    {
                        component = key;
                    }
                }
                EditorGUILayout.EndHorizontal();
            }
            else
            {
                scriptObj = (MonoScript)EditorGUILayout.ObjectField(scriptObj, typeof(MonoScript), true);
            }
        }
    }
    #endregion class 含有Component

    #region class 增删Component
    class AfterDealComponentTool : Phase<FindResult, string>
    {
        private bool isRemoveMissComponent = true;
        private MonoScript addScript;
        private MonoScript removeScript;
        override public string FuncReturn(FindResult input)
        {
            var str = "";
            if (isRemoveMissComponent)
            {
                GameObjectUtility.RemoveMonoBehavioursWithMissingScript(input.go);
            }
            if (input.extraObjs != null)
            {
                for (int i = 0; i < input.extraObjs.Count; ++i)
                {
                    var com = input.extraObjs[i];
                    var name = com == null ? "null" : com.name;
                    GameObject.DestroyImmediate(com, true);

                    str += input.path + " - " + name + "\r\n";
                }
            }

            if (removeScript != null)
            {
                var cl = input.go.GetComponents(removeScript.GetClass());
                for (int i = 0; i < cl.Length; ++i)
                {
                    var com = cl[i];
                    GameObject.DestroyImmediate(com, true);
                    str += input.path + " - " + removeScript.name + "\r\n";
                }
            }

            if (addScript != null)
            {
                input.go.AddComponent(addScript.GetClass());
                str += input.path + " + " + addScript.name + "\r\n";
            }

            return str;
        }

        override public void OnDraw()
        {
            isRemoveMissComponent = GUILayout.Toggle(isRemoveMissComponent, "清除miss的组件");
            removeScript = (MonoScript)EditorGUILayout.ObjectField("删除：", removeScript, typeof(MonoScript), true);
            addScript = (MonoScript)EditorGUILayout.ObjectField("添加：", addScript, typeof(MonoScript), true);
        }

        override public string CheckNeed(bool isSave, SearchRange sr, bool isDS, HitRule hr, AfterDeal ad)
        {
            if (!isSave)
            {
                return "需要启用保存prefab功能";
            }
            return "";
        }
    }
    #endregion class 增删Component

    #region class UI规范化
    private class AfterDealFormatPrefab : Phase<FindResult, string>
    {
        private int roundNum = 1;
        public override void PreLoading()
        {
            LanguageEditorTool.RefreshLanguageJsonData();
        }

        override public string FuncReturn(FindResult input)
        {
            var str = "";
            var tags = "";

            //if (input.go.transform.parent == null && input.go.GetComponent<CanvasScaler>() != null) //Check Root
            //{
            //    var root = input.go.transform;

            //    var canvasScaler = root.GetComponent<CanvasScaler>();
            //    if (canvasScaler.screenMatchMode != CanvasScaler.ScreenMatchMode.Expand)
            //    {
            //        canvasScaler.screenMatchMode = CanvasScaler.ScreenMatchMode.Expand;
            //        tags += "[CanvasScaler Mode Wrong]";
            //    }
            //    if (root.GetComponent<CanvasGroup>() == null)
            //    {
            //        input.go.AddComponent<CanvasGroup>();
            //        tags += "[CanvasGroup not found]";
            //    }

            //    // 基础格式检查
            //    if (root.childCount != 0)
            //    {
            //        var findUINode = true;
            //        var uiNode = root.GetChild(0);
            //        if (uiNode.CompareTag("UINode") || uiNode.name == "UINode")
            //        {
            //            findUINode = true;
            //        }
            //        else if (root.childCount >= 2)
            //        {
            //            uiNode = root.GetChild(1);
            //            if (uiNode.CompareTag("UINode") || uiNode.name == "UINode")
            //            {
            //                findUINode = true;
            //            }
            //            else
            //            {
            //                findUINode = false;
            //                uiNode = null;
            //            }
            //        }
            //        else
            //        {
            //            findUINode = false;
            //            uiNode = null;
            //        }

            //        if (!findUINode)
            //        {
            //            tags += "[UINode not found]";
            //            //EditorUtility.DisplayDialog("错误", "基础界面结构不正确", "OK");
            //        }
            //        else
            //        {
            //            var rectNode = uiNode as RectTransform;
            //            if (rectNode != null)
            //            {
            //                rectNode.anchorMin = new Vector2(0, 0);
            //                rectNode.anchorMax = new Vector2(1, 1);
            //                rectNode.sizeDelta = new Vector2(0, 0);
            //            }

            //            if (!uiNode.CompareTag("UINode"))
            //            {
            //                uiNode.tag = "UINode";
            //                tags += "[UINode tag error]";
            //            }
            //        }
            //    }
            //}

            // Transform清除小数点，z值设置为0
            //var rect = input.go.GetComponent<RectTransform>();
            //if (rect != null)
            //{
            //    //roundNum = 0;
            //    //var anchorMax = rect.anchorMax;
            //    //var anchorMaxRound = roundNum < 3 ? 3 : roundNum;
            //    //rect.anchorMax = new Vector2((float)System.Math.Round(anchorMax.x, anchorMaxRound), (float)System.Math.Round(anchorMax.y, anchorMaxRound));

            //    //var anchorMin = rect.anchorMin;
            //    //var anchorMinRound = roundNum < 3 ? 3 : roundNum;
            //    //rect.anchorMin = new Vector2((float)System.Math.Round(anchorMin.x, anchorMinRound), (float)System.Math.Round(anchorMin.y, anchorMinRound));

            //    var pos = rect.localPosition;
            //    if (roundNum == 0)
            //    {
            //        rect.localPosition = new Vector3((int)System.Math.Round(pos.x, roundNum), (int)System.Math.Round(pos.y, roundNum), 0);
            //    }
            //    else
            //    {
            //        rect.localPosition = new Vector3((float)System.Math.Round(pos.x, roundNum), (float)System.Math.Round(pos.y, roundNum), 0);
            //    }
            //    var size = rect.sizeDelta;
            //    if (roundNum == 0)
            //    {
            //        rect.sizeDelta = new Vector2((int)System.Math.Round(size.x, roundNum), (int)System.Math.Round(size.y, roundNum));
            //    }
            //    else
            //    {
            //        rect.sizeDelta = new Vector2((float)System.Math.Round(size.x, roundNum), (float)System.Math.Round(size.y, roundNum));
            //    }
            //    var offsetMin = rect.offsetMin;
            //    if (roundNum == 0)
            //    {
            //        rect.offsetMin = new Vector2((int)System.Math.Round(offsetMin.x, roundNum), (int)System.Math.Round(offsetMin.y, roundNum));
            //    }
            //    else
            //    {
            //        rect.offsetMin = new Vector2((float)System.Math.Round(offsetMin.x, roundNum), (float)System.Math.Round(offsetMin.y, roundNum));
            //    }
            //    var offsetMax = rect.offsetMax;
            //    if (roundNum == 0)
            //    {
            //        rect.offsetMax = new Vector2((int)System.Math.Round(offsetMax.x, roundNum), (int)System.Math.Round(offsetMax.y, roundNum));
            //    }
            //    else
            //    {
            //        rect.offsetMax = new Vector2((float)System.Math.Round(offsetMax.x, roundNum), (float)System.Math.Round(offsetMax.y, roundNum));
            //    }
            //    var scale = rect.localScale;
            //    var scaleRound = roundNum < 2 ? 2 : roundNum;
            //    rect.localScale = new Vector3((float)System.Math.Round(scale.x, scaleRound), (float)System.Math.Round(scale.y, scaleRound), (float)System.Math.Round(scale.z, scaleRound));
            //}

            //  删除非法空字符：\x0d
            //  RayCastTarget删除
            //var text = input.go.GetComponent<Text>();
            //if (text != null)
            //{
            //    if (text.raycastTarget)
            //    {
            //        Transform parent = input.go.transform.parent;
            //        if (parent.GetComponent<InputField>() == null)
            //        {
            //            text.raycastTarget = false;
            //            tags += "[text raycast]";
            //        }
            //    }

            //    text.text = text.text.Replace('\x0d', ' ');
            //}

            //var tmp = input.go.GetComponent<TextMeshProUGUI>();
            //if (tmp != null)
            //{
            //    if (tmp.raycastTarget)
            //    {
            //        Transform parent = input.go.transform.parent;
            //        if (parent && parent.GetComponent<InputField>() == null/* && input.go.GetComponent<Framework.UI.TMPClickListener>() == null*/)
            //        {
            //            tmp.raycastTarget = false;
            //            tags += "[text raycast]";
            //        }
            //    }

            //    if (tmp.text != null)
            //        tmp.text = tmp.text.Replace('\x0d', ' ');
            //}

            //var inputField = input.go.GetComponent<InputField>();
            //if (inputField != null)
            //{
            //    if (!inputField.textComponent.raycastTarget)
            //    {
            //        inputField.textComponent.raycastTarget = true;
            //        tags += "[InputField raycast]";
            //    }
            //    if (!inputField.targetGraphic.raycastTarget)
            //    {
            //        inputField.targetGraphic.raycastTarget = true;
            //        tags += "[InputField raycast]";
            //    }
            //}

            // Navigation关闭
            var btn = input.go.GetComponent<Selectable>();
            if (btn != null)
            {
                var navigation = new Navigation { mode = Navigation.Mode.None };
                if (btn.navigation.mode != Navigation.Mode.None)
                {
                    btn.navigation = navigation;
                    tags += "[navigation]";
                }
            }

            // 空的CanvasRender删除
            var render = input.go.GetComponent<CanvasRenderer>();
            if (render != null)
            {
                if (input.go.GetComponents<Graphic>().Length == 0)
                {
                    UnityEngine.Object.DestroyImmediate(render, true);
                    tags += "[empty renderer]";
                }
            }

            // 空的DOTweenAnimation删除
            var dotManager = input.go.GetComponent<DOTweenVisualManager>();
            if (dotManager != null)
            {
                if (input.go.GetComponents<DOTweenAnimation>().Length == 0)
                {
                    UnityEngine.Object.DestroyImmediate(dotManager, true);
                    tags += "[empty dotManager]";
                }
            }

            //  检查资源的路径是不是来自非法路径:FORBID_UI_PATH
            //var graphic = input.go.GetComponent<Graphic>();
            //if (graphic != null)
            //{
            //    var path = AssetDatabase.GetAssetPath(graphic.mainTexture);
            //    if (!string.IsNullOrEmpty(path))
            //    {
            //        if (path.Contains(FORBID_UI_PATH))
            //        {
            //            tags += "[forbid resources]";
            //            EditorUtility.DisplayDialog("错误", string.Format("资源引用错误，在{0}", input.path), "OK");
            //        }
            //    }
            //}
            //var selectable = input.go.GetComponent<Selectable>();
            //if (selectable != null)
            //{
            //    var path = AssetDatabase.GetAssetPath(selectable.spriteState.highlightedSprite);
            //    if (!string.IsNullOrEmpty(path))
            //    {
            //        if (path.Contains(FORBID_UI_PATH))
            //        {
            //            tags += "[forbid resources h]";
            //            EditorUtility.DisplayDialog("错误", string.Format("资源引用错误，在{0}的highlightedSprite", input.path), "OK");
            //        }
            //    }
            //    path = AssetDatabase.GetAssetPath(selectable.spriteState.pressedSprite);
            //    if (!string.IsNullOrEmpty(path))
            //    {
            //        if (path.Contains(FORBID_UI_PATH))
            //        {
            //            tags += "[forbid resources p]";
            //            EditorUtility.DisplayDialog("错误", string.Format("资源引用错误，在{0}的pressedSprite", input.path), "OK");
            //        }
            //    }
            //    path = AssetDatabase.GetAssetPath(selectable.spriteState.disabledSprite);
            //    if (!string.IsNullOrEmpty(path))
            //    {
            //        if (path.Contains(FORBID_UI_PATH))
            //        {
            //            tags += "[forbid resources d]";
            //            EditorUtility.DisplayDialog("错误", string.Format("资源引用错误，在{0}的disabledSprite", input.path), "OK");
            //        }
            //    }
            //}

            //Button检查，保证勾选上interactable，然后interactable只能由程序来修改。
            //var button = input.go.GetComponent<Button>();
            //if (button != null)
            //{
            //    if (!button.interactable)
            //    {
            //        tags += "[Button not interactable]";
            //        button.interactable = true;
            //    }
            //}

            //  LazyEffectPlayer路径修复
            //var lep = input.go.GetComponent<LazyEffectPlayer>();
            //if (lep != null)
            //{
            //    var report = lep.RefreshEffectPath();
            //    tags += report;
            //}

            //  文本id查找
            var myText = input.go.GetComponent<MyText>();
            if (myText != null)
            {
                var errorCode = LanguageEditorTool.ReplaceTextID(myText);
                switch (errorCode)
                {
                    case -1:
                        tags += "[LanguageID Not Found]";
                        break;
                    case -2:
                        tags += "[LanguageID Multi Found]";
                        break;
                    case -3:
                        tags += "[LanguageID Similar Found]";
                        break;
                }
            }

            if (!string.IsNullOrEmpty(tags))
            {
                str = tags + input.path;
            }
            return str;
        }

        override public void OnDraw()
        {
            roundNum = EditorGUILayout.IntField("保留位数： ", roundNum);
        }

        override public string CheckNeed(bool isSave, SearchRange sr, bool isDS, HitRule hr, AfterDeal ad)
        {
            if (!isSave)
            {
                return "需要启用保存prefab功能";
            }
            if (!isDS)
            {
                return "需要启用深度查找功能";
            }
            return "";
        }
    }
    #endregion class UI规范化

    #region class 文字射线
    class AfterDealTextRaycast : Phase<FindResult, string>
    {
        override public string FuncReturn(FindResult input)
        {
            var str = "";
            var text = input.go.GetComponent<Text>();
            if (text != null)
            {
                if (text.raycastTarget)
                {
                    text.raycastTarget = false;
                    str = input.path;
                }
            }

            var tmp = input.go.GetComponent<TextMeshProUGUI>();
            if (tmp != null)
            {
                if (tmp.raycastTarget)
                {
                    tmp.raycastTarget = false;
                    str = input.path;
                }
            }

            var inputField = input.go.GetComponent<InputField>();
            if (inputField != null)
            {
                inputField.textComponent.raycastTarget = true;
                inputField.targetGraphic.raycastTarget = true;
                str = input.path;
            }

            return str;
        }

        override public void OnDraw()
        {
            EditorGUILayout.LabelField("如果查找的是Text或者TMP组件，则删除raycast。如果查找的是InputField组件，则添加回对应text的raycast");
        }

        override public string CheckNeed(bool isSave, SearchRange sr, bool isDS, HitRule hr, AfterDeal ad)
        {
            if (!isSave)
            {
                return "需要启用保存prefab功能";
            }
            if (!isDS)
            {
                return "需要启用深度查找功能";
            }
            if (hr != HitRule.含有Component)
            {
                return "需要启用命中Text组件或TextMeshProUGUI组件的判断";
            }
            return "";
        }
    }
    #endregion class 文字射线

    #region class 默认字体
    class AfterDealDefaultFont : Phase<FindResult, string>
    {
        override public string FuncReturn(FindResult input)
        {
            var str = "";
            var com = input.go.GetComponent<Text>();
            if (com != null)
            {
                if (com.font.name == "Arial")
                {
                    str = input.path;
                }
            }
            return str;
        }

        override public string CheckNeed(bool isSave, SearchRange sr, bool isDS, HitRule hr, AfterDeal ad)
        {
            if (!isDS)
            {
                return "需要启用深度查找功能";
            }
            if (hr != HitRule.含有Component)
            {
                return "需要启用命中Text组件的判断";
            }
            return "";
        }
    }
    #endregion class 默认字体

    #region class 检查TMP的边距
    class AfterDealTMPMargins : Phase<FindResult, string>
    {
        override public string FuncReturn(FindResult input)
        {
            var str = "";
            var com = input.go.GetComponent<TextMeshProUGUI>();
            if (com != null)
            {
                if (com.margin.x > float.Epsilon)
                {
                    str = input.path + " Margins: " + com.margin;
                }
                else if (com.margin.y > float.Epsilon)
                {
                    str = input.path + " Margins: " + com.margin;
                }
                else if (com.margin.z > float.Epsilon)
                {
                    str = input.path + " Margins: " + com.margin;
                }
                else if (com.margin.w > float.Epsilon)
                {
                    str = input.path + " Margins: " + com.margin;
                }
            }
            return str;
        }

        override public string CheckNeed(bool isSave, SearchRange sr, bool isDS, HitRule hr, AfterDeal ad)
        {
            if (!isDS)
            {
                return "需要启用深度查找功能";
            }
            if (hr != HitRule.含有Component)
            {
                return "需要启用命中TMP组件的判断";
            }
            return "";
        }
    }
    #endregion class 检查TMP的边距

    #region class 检查UI材质
    class AfterDealNoneImage : Phase<FindResult, string>
    {
        override public string FuncReturn(FindResult input)
        {
            var str = "";
            var com = input.go.GetComponent<Graphic>();
            if (com != null)
            {
                if (com.material != null && !com.material.HasProperty(ShaderProperty_MainTex))
                {
                    str = input.path + " , " + com.material.name;
                }
            }

            return str;
        }

        override public string CheckNeed(bool isSave, SearchRange sr, bool isDS, HitRule hr, AfterDeal ad)
        {
            if (!isDS)
            {
                return "需要启用深度查找功能";
            }
            if (hr == HitRule.None)
            {
                return "需要启用命中判断";
            }
            return "";
        }
    }
    #endregion class 检查UI材质

    #region class 查找未使用图集的Image
    class AfterDealUnTGAImage : Phase<FindResult, string>
    {
        override public string FuncReturn(FindResult input)
        {
            var str = "";
            var com = input.go.GetComponent<Image>();
            str = AssetDatabase.GetAssetPath(com.sprite);
            if (!str.EndsWith(".tga"))
            {
                return input.path;
            }
            return "";
        }
    }
    #endregion class 查找未使用图集的Image

    #region class 分析prefab成分
    class AfterDealAnalyzePrefab : Phase<FindResult, string>
    {
    }
    #endregion class 分析prefab成分

    //临时
    #region class blur修复
    class AfterDealBlurPrefab : Phase<FindResult, string>
    {
        override public string FuncReturn(FindResult input)
        {
            var str = "";
            var com = input.go.GetComponent<Transform>();
            if (com.childCount == 1)
            {
                var childRect = com.GetChild(0) as RectTransform;
                if (childRect != null)
                {
                    childRect.anchorMin = Vector2.zero;
                    childRect.anchorMax = Vector2.one;
                    childRect.sizeDelta = Vector2.zero;
                    return input.path + childRect.sizeDelta;
                }
            }
            return "";
        }
    }
    #endregion class blur修复

    //#region class 文字控件解析
    //class AfterDealX2UIWindowAsset : Phase<FindResult, string>
    //{
    //    public static int languageIdStart = 1;
    //    public static string commaStr = "$%";
    //    public static string lineStr = "$-";
    //    public bool DOClear = false;
    //    override public string FuncReturn(FindResult input)
    //    {
    //        LogicHelper.InitLogic();
    //        var str = "";
    //        var com = input.go.GetComponent<X2UIWindowAsset>();

    //        if (DOClear)
    //        {
    //            if (com.Texts != null && com.Texts.Count > 0)
    //            {
    //                // 查找已保存的文字跟id
    //                //str += input.path + "[" + com.Texts.Count + "];";
    //                //foreach (var data in com.Texts)
    //                //{
    //                //    if (data.mTextMesh != null)
    //                //    {
    //                //        str += " TMP:[" + data.mTextMesh.text + "] " + " TMPID:[" + data.id + "] ";
    //                //    }
    //                //    if (data.mText != null)
    //                //    {
    //                //        str += " Text:[" + data.mText.text + "] " + " TextID:[" + data.id + "] ";
    //                //    }

    //                //    str += ";";
    //                //}

    //                // 将已保存的文字从language表查到对应的文字之后，把文字填入对应组件，然后删除保存的文字id
    //                //str += input.path + "[" + com.Texts.Count + "];";
    //                //foreach (var data in com.Texts)
    //                //{
    //                //    if (data.id != 0)
    //                //    {
    //                //        if (data.mTextMesh != null)
    //                //        {
    //                //            data.mTextMesh.text = GameAPI.GetLanguageStr(data.id);
    //                //        }
    //                //        else if (data.mText != null)
    //                //        {
    //                //            data.mText.text = GameAPI.GetLanguageStr(data.id);
    //                //        }
    //                //        data.id = 0;
    //                //    }
    //                //}

    //                // 清空保存的文字
    //                com.Texts.Clear();
    //            }
    //        }
    //        else
    //        {
    //            var meshText = com.GetComponentsInChildren<TextMeshProUGUI>(true);
    //            var texts = com.GetComponentsInChildren<Text>(true);
    //            foreach (TextMeshProUGUI child in meshText)
    //            {
    //                if (string.IsNullOrEmpty(child.text.Trim()))
    //                    continue;

    //                bool hasOldText = false;
    //                for (int i = 0; i < com.Texts.Count; ++i)
    //                {
    //                    if (child == com.Texts[i].mTextMesh)
    //                    {
    //                        hasOldText = true;
    //                        break;
    //                    }
    //                }
    //                if (hasOldText)
    //                    continue;

    //                var data = new Data()
    //                {
    //                    id = languageIdStart,
    //                    mTextMesh = child
    //                };
    //                com.Texts.Add(data);
    //                var text = data.mTextMesh.text;
    //                text = text.Replace(",", commaStr);
    //                text = text.Replace("\r\n", lineStr);
    //                text = text.Replace("\n", lineStr);
    //                str += data.id + "," + text + "," + child.transform.GetPath() + "," +
    //                       (checkButton(child.transform) ? "1" : "0") + "\r\n";
    //                languageIdStart++;
    //            }
    //            foreach (Text child in texts)
    //            {
    //                if (string.IsNullOrEmpty(child.text.Trim()))
    //                    continue;

    //                bool hasOldText = false;
    //                for (int i = 0; i < com.Texts.Count; ++i)
    //                {
    //                    if (child == com.Texts[i].mText)
    //                    {
    //                        hasOldText = true;
    //                        break;
    //                    }
    //                }
    //                if (hasOldText)
    //                    continue;

    //                var data = new Data()
    //                {
    //                    id = languageIdStart,
    //                    mText = child
    //                };
    //                com.Texts.Add(data);
    //                var text = data.mText.text;
    //                text = text.Replace(",", commaStr);
    //                text = text.Replace("\r\n", lineStr);
    //                text = text.Replace("\n", lineStr);
    //                str += data.id + "," + text + "," + child.transform.GetPath() + "," +
    //                       (checkButton(child.transform) ? "1" : "0") + "\r\n";
    //                languageIdStart++;
    //            }
    //        }

    //        return str;
    //    }

    //    private bool checkButton(Transform trans)
    //    {
    //        var t = trans;
    //        while (t != null)
    //        {
    //            var btn = t.GetComponent<Button>();
    //            if (btn != null)
    //                return true;

    //            t = t.parent;
    //        }

    //        return false;
    //    }

    //    override public void OnDraw()
    //    {
    //        EditorGUILayout.BeginHorizontal();
    //        GUILayout.Label("勾上表示清除原有id，不勾表示增量生成新的id", GUILayout.MaxWidth(250));
    //        DOClear = EditorGUILayout.Toggle(DOClear);
    //        EditorGUILayout.EndHorizontal();
    //        GUILayout.Space(10);
    //        if (!DOClear)
    //        {
    //            EditorGUILayout.BeginHorizontal();
    //            GUILayout.Label("id起始值（原表中没有出现过的id）", GUILayout.MaxWidth(200));
    //            languageIdStart = EditorGUILayout.IntField(languageIdStart);
    //            EditorGUILayout.EndHorizontal();
    //            commaStr = EditorGUILayout.TextField("逗号替换成：", commaStr);
    //            lineStr = EditorGUILayout.TextField("换行替换成：", lineStr);
    //            if (GUILayout.Button("输出成CSV"))
    //            {
    //                StartFind();

    //                if (mResultLog.Count == 0)
    //                {
    //                    EditorUtility.DisplayDialog("提示", "没有查找结果", "OK");
    //                    return;
    //                }

    //                var printFileName = "LanguageUI_Append";
    //                if (!Directory.Exists(printFileName))
    //                {
    //                    Directory.CreateDirectory(printFileName);
    //                }

    //                using (FileStream fs = new FileStream(printFileName + Path.DirectorySeparatorChar + printFileName + ".csv", FileMode.Create))
    //                {
    //                    var sw = new StreamWriter(fs, Encoding.Default);
    //                    foreach (var kv in mResultLog)
    //                    {
    //                        var list = kv.details;
    //                        for (int i = 0, len = list.Count; i < len; ++i)
    //                        {
    //                            var line = list[i];
    //                            if (string.IsNullOrEmpty(line) || line.Trim() == "")
    //                            {
    //                                continue;
    //                            }
    //                            sw.Write(line);
    //                        }
    //                    }
    //                    sw.Close();
    //                }
    //                string resultDir = Path.GetFullPath(printFileName) + Path.DirectorySeparatorChar;
    //                System.Diagnostics.Process.Start(resultDir);
    //            }
    //        }
    //    }

    //    override public string CheckNeed(bool isSave, SearchRange sr, bool isDS, HitRule hr, AfterDeal ad)
    //    {
    //        if (!isSave)
    //        {
    //            return "需要启用保存prefab功能";
    //        }

    //        return "";
    //    }
    //}
    //#endregion class 文字控件解析

    //#region class 文字控件查找
    //class AfterFindX2UIWindowAsset : Phase<FindResult, string>
    //{
    //    public static int min = 10000;
    //    override public string FuncReturn(FindResult input)
    //    {
    //        LogicHelper.InitLogic();
    //        var str = "";
    //        var com = input.go.GetComponent<X2UIWindowAsset>();

    //        if (com != null && com.Texts != null && com.Texts.Count > 0)
    //        {
    //            for (int i = 0; i < com.Texts.Count; ++i)
    //            {
    //                int id = com.Texts[i].id;
    //                var table = LanguageManager.Instance.GetItem(id);
    //                if (table != null && id > min)
    //                {
    //                    str += id.ToString() + ":" + table.Chinese + "\n";
    //                }
    //            }
    //        }

    //        return str;
    //    }

    //    override public void OnDraw()
    //    {
    //        EditorGUILayout.BeginHorizontal();
    //        GUILayout.Label("该工具只是用来查找残留的LanguageID", GUILayout.MaxWidth(250));
    //        EditorGUILayout.EndHorizontal();
    //        min = EditorGUILayout.IntField("ID最小值：", min);
    //    }
    //}
    //#endregion class 文字控件查找

    #region class 根据tag把文字引用中的程序修改文字剔除
    class AfterFindX2UIControlDataTagAsset : Phase<FindResult, string>
    {
        override public string FuncReturn(FindResult input)
        {
            var str = "";
            //var com = input.go.GetComponent<X2UIWindowAsset>();

            //if (com != null && com.Texts != null && com.Texts.Count > 0)
            //{
            //    for (int i = 0; i < com.Texts.Count; ++i)
            //    {
            //        var text = com.Texts[i].mText;
            //        if (text != null)
            //        {
            //            var tag = text.gameObject.tag;
            //            if (tag == "UI_ControlData" || tag == "UI_ControlDataList")
            //            {
            //                str += com.Texts[i].id + ",";
            //            }
            //        }
            //        var tmp = com.Texts[i].mTextMesh;
            //        if (tmp != null)
            //        {
            //            var tag = tmp.gameObject.tag;
            //            if (tag == "UI_ControlData" || tag == "UI_ControlDataList")
            //            {
            //                str += com.Texts[i].id + ",";
            //            }
            //        }
            //    }
            //}

            return str;
        }

        override public void OnDraw()
        {
            EditorGUILayout.BeginHorizontal();
            GUILayout.Label("根据tag把文字引用中的程序修改文字剔除", GUILayout.MaxWidth(250));
            EditorGUILayout.EndHorizontal();
        }
        override public string CheckNeed(bool isSave, SearchRange sr, bool isDS, HitRule hr, AfterDeal ad)
        {
            if (!isSave)
            {
                return "需要启用保存prefab功能";
            }
            return "";
        }
    }
    #endregion class 根据tag把文字引用中的程序修改文字剔除

    #region class 动画表情散图查找替换
    class AfterDealX2ExpressionReplaceSprite : Phase<FindResult, string>
    {
        private string targetPath = "Assets/Resources/UIAltas/Expression/";
        override public string FuncReturn(FindResult input)
        {
            var str = "";
            if (input != null)
            {
            }
            return str;
        }

        override public string CheckNeed(bool isSave, SearchRange sr, bool isDS, HitRule hr, AfterDeal ad)
        {
            if (!isSave)
            {
                return "需要启用保存prefab功能";
            }
            return "";
        }
    }
    #endregion class 动画表情散图查找替换

    #region class 检查按钮Highlight命名
    class AfterDealCheckButtonHighlightedName : Phase<FindResult, string>
    {
        override public string FuncReturn(FindResult input)
        {
            var str = "";
            if (input != null)
            {
                var btn = input.go.GetComponent<Button>();
                if (btn.animationTriggers.highlightedTrigger == "Highlight")
                {
                    str += string.Format("{0}所在的{1}名字不对\n", input.path, btn.animationTriggers.highlightedTrigger);
                    btn.animationTriggers.highlightedTrigger = "Highlighted";
                }
            }
            return str;
        }

        override public string CheckNeed(bool isSave, SearchRange sr, bool isDS, HitRule hr, AfterDeal ad)
        {
            if (!isSave)
            {
                return "需要启用保存prefab功能";
            }
            return "";
        }
    }
    #endregion class 检查按钮Highlight命名

    #region class 检查SingleFrameAni序列帧命名规范
    class AfterDealCheckSingleFrameAniSpriteName : Phase<FindResult, string>
    {
        override public string FuncReturn(FindResult input)
        {
            var str = "";
            if (input != null)
            {
                var ani = input.go.GetComponent<SingleFrameAni>();
                if (ani != null)
                {
                    Sprite firstSprite = null;
                    var rootPath = "";
                    int tag = 0; //1-没有_数字；2-有null；4-数字不递增；8-图片来自不同路径；16-当前文档有可增加的图片；
                    for (int i = 0; i < ani.sprites.Count; i++)
                    {
                        var sp = ani.sprites[i];
                        if (sp == null)
                        {
                            tag |= 2;
                            continue;
                        }

                        if (firstSprite == null)
                            firstSprite = sp;

                        if (string.IsNullOrEmpty(rootPath))
                        {
                            rootPath = Path.GetDirectoryName(AssetDatabase.GetAssetPath(sp));
                        }
                        else
                        {
                            if (rootPath != Path.GetDirectoryName(AssetDatabase.GetAssetPath(sp)))
                            {
                                tag |= 8;
                                continue;
                            }
                        }

                        if (!sp.name.Contains('_'))
                        {
                            tag |= 1;
                            continue;
                        }

                        if (i == 0 || ani.sprites[i - 1] == null)
                            continue;

                        var spNameList = sp.name.Split('_');
                        if (int.TryParse(spNameList[spNameList.Length - 1], out var spIndex))
                        {
                            var spPreNameList = ani.sprites[i - 1].name.Split('_');
                            if (int.TryParse(spPreNameList[spPreNameList.Length - 1], out var spPreIndex))
                            {
                                if (i > 0 && (spIndex - 1) == spPreIndex)
                                {
                                    continue;
                                }
                                else
                                {
                                    tag |= 4;
                                    continue;
                                }
                            }
                            else
                            {
                                tag |= 1;
                                continue;
                            }
                        }
                        else
                        {
                            tag |= 1;
                            continue;
                        }
                    }

                    if (!string.IsNullOrEmpty(rootPath) && firstSprite.name.Contains('_'))
                    {
                        var preName = firstSprite.name.Substring(0, firstSprite.name.LastIndexOf('_'));
                        var fileList = new List<string>();
                        string[] files = Directory.GetFiles(rootPath, "*.png", SearchOption.TopDirectoryOnly);
                        foreach (var f in files)
                        {
                            var f2 = Path.GetFileNameWithoutExtension(f);
                            if (f2.StartsWith(preName))
                            {
                                fileList.Add(f2);
                            }
                        }

                        if (ani.sprites.Count != fileList.Count)
                        {
                            tag |= 16;
                        }
                    }

                    if (tag != 0)
                        str += input.path + ", [TAG]" + tag + ", firstSprite=" + firstSprite.name + ", spritePath=" + AssetDatabase.GetAssetPath(firstSprite);
                }
            }
            return str;
        }
    }
    #endregion class 检查SingleFrameAni序列帧命名规范

    #region class 检查controller下的动画是否有legacy
    class AfterDealControllerLegacy : Phase<FindResult, string>
    {
        override public string FuncReturn(FindResult input)
        {
            var str = "";
            if (input != null)
            {
                var ac = input.rawObj as AnimatorController;
                if (ac != null)
                {
                    //UnityEngine.Object[] allAsset = input.rawObj.GetType() != typeof(SceneAsset) ?  //学习
                    //    AssetDatabase.LoadAllAssetsAtPath(input.path).Where(asset => asset != null).ToArray() :
                    //    new UnityEngine.Object[] { input.rawObj };

                    UnityEngine.Object[] allAsset = AssetDatabase.LoadAllAssetsAtPath(input.path).Where(asset => asset != null).ToArray();
                    for (int i = 0; i < allAsset.Length; i++)
                    {
                        var subAsset = allAsset[i];
                        if (subAsset != null && subAsset.GetType() == typeof(AnimationClip))
                        {
                            var ani = subAsset as AnimationClip;
                            if (ani.legacy)
                            {
                                str += input.path + " @ " + subAsset.ToString() + "\n";
                            }
                        }
                    }

                    ////HierarchyProperty property = new HierarchyProperty(input.path);  //学习
                    ////Debug.LogError("  >> property " + property + " , " + property.isFolder + " , " + property.hasChildren + " , " + property.guid + " , " + property.name+ " , ");


                    ////var path = AssetDatabase.GUIDToAssetPath(property.guid);
                    ////var subFolders = AssetDatabase.GetSubFolders(path);
                    ////Debug.LogError(" >> subfolders " + subFolders.Length);
                    ////foreach (var subname in subFolders)
                    ////{
                    ////    Debug.LogError("  >> subname " + subname);
                    ////}


                    ////property = new HierarchyProperty("Assets");
                    ////Debug.LogError("  >> property2 " + property + " , " + property.isFolder + " , " + property.hasChildren + " , " + property.guid + " , " + property.name + " , ");


                    ////path = AssetDatabase.GUIDToAssetPath(property.guid);
                    ////subFolders = AssetDatabase.GetSubFolders(path);
                    ////Debug.LogError(" >> subfolders2 " + subFolders.Length);
                    ////foreach (var subname in subFolders)
                    ////{
                    ////    Debug.LogError("  >> subname2 " + subname);
                    ////}
                }
            }
            return str;
        }
    }
    #endregion class 检查controller下的动画是否有legacy

    #region class 检查controller下的状态机是否为空motion
    class AfterDealControllerEmptyState : Phase<FindResult, string>
    {
        override public string FuncReturn(FindResult input)
        {
            var str = "";
            if (input != null)
            {
                var ac = input.rawObj as AnimatorController;
                if (ac != null)
                {
                    var stateMachine = ac.layers[0].stateMachine;
                    foreach (var state in stateMachine.states)
                    {
                        if (state.state.motion == null)
                        {
                            str += string.Format("{0}的状态{1}里的动画为空\n", ac, state.state.name);
                        }
                        if (state.state.name == "Highlight")
                        {
                            str += string.Format("{0}的状态{1}名字推荐改为Highlighted\n", ac, state.state.name);
                        }
                    }
                }
            }
            return str;
        }
    }
    #endregion class 检查controller下的状态机是否为空motion

    #region class 一键替换LanguageID
    class AfterDealReplaceLanguageID : Phase<FindResult, string>
    {
        public override void PreLoading()
        {
            LanguageEditorTool.RefreshLanguageJsonData();
        }

        override public string FuncReturn(FindResult input)
        {
            MyText com = input.go.GetComponent<MyText>();
            if (com == null) return "";
            var errorCode = LanguageEditorTool.ReplaceTextID(com);
            switch (errorCode)
            {
                case -1:
                    return string.Format("没匹配到译文, path:{0}, Chinese:{1}", input.path, com.text);
                case -2:
                    return string.Format("匹配到多个译文, path:{0}, Chinese:{1}", input.path, com.text);
                case -3:
                    return string.Format("匹配到相似译文, path:{0}, Chinese:{1}", input.path, com.text);
                //default:
                //return string.Format("其他情况, path:{0}, Chinese:{1}, code:{2}", input.path, com.text, errorCode);
            }
            return "";
        }
    }
    #endregion class 一键替换LanguageID

    private bool DrawAfterDeal()
    {
        bool isOK = true;
        EditorGUILayout.BeginVertical("Box");

        mAfterDeal = (AfterDeal)EditorGUILayout.EnumPopup("后续处理：", mAfterDeal, GUILayout.MinWidth(100));
        if (AfterDealClass != null && AfterDealClass.ContainsKey(mAfterDeal))
        {
            var cls = AfterDealClass[mAfterDeal];
            var warning = cls.CheckNeed(mIsSavePrefab, mSearchRange, mIsDeepSearch, mHitRule, mAfterDeal);
            if (!string.IsNullOrEmpty(warning))
            {
                isOK = false;
                EditorGUILayout.HelpBox(warning, MessageType.Error);
            }
            cls.OnDraw();
        }

        EditorGUILayout.EndVertical();
        return isOK;
    }
}
#endif

